//server.c
//====================================================================

#include "test/globaldef.h"
#include "test/socket.h"
#define SERVER_PORT    9100
#define LENGTH_OF_LISTEN_QUEUE 20
#define FILE_NAME_MAX_SIZE 512

extern QUEUE_TYPE  Rd_Input_Q;
extern pthread_mutex_t Rd_Input_Q_Mut;
extern QUEUE_TYPE  Rd_Free_Q;
extern pthread_mutex_t Rd_Free_Q_Mut;
extern U_INT8 Rd_Buf[NUM_RD_PACKETS][RD_BUF_SIZE];

extern QUEUE_TYPE  Wr_Output_Q[NUM_PORTS];
extern pthread_mutex_t Wr_Output_Q_Mut;
extern QUEUE_TYPE  Wr_Free_Q;
extern pthread_mutex_t Wr_Free_Q_Mut;

int packet_append(U_INT16 chan, char* buffer, int buff_length);
int packet_read(U_INT16 chan, char* buffer, int buff_length);
static int server_socket = -1;
static int new_server_socket = -1;
static int socket_init()
{
  struct sockaddr_in server_addr;
  bzero(&server_addr,sizeof(server_addr)); //set all the buffers to be zero 
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htons(INADDR_ANY);
  server_addr.sin_port = htons(SERVER_PORT);

  // create (TCP)socket,use server_socket as the server socket
  server_socket = socket(PF_INET,SOCK_STREAM,0);
  if( server_socket < 0)
  {
    mLog("Create Socket Failed!");
    return -1;
  }
  else
  {
    int opt =1;
    setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
  }

  //bind the socket with the addr
  if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))
  {
    mLog("Server Bind Port : %d Failed!", SERVER_PORT);
    return -1;
  }

  //server_socket listen
  if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) )
  {
    mLog("Server Listen Failed!");
    return -1;
  }
  return 0;
}
static int socket_accept()
{
  struct sockaddr_in client_addr;
  socklen_t length = sizeof(client_addr);

  //waiting the client connect with server
  new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length);
  if ( new_server_socket < 0)
  {
    mLog("Server Accept Failed!\n");
    return -1;
  }
  int flags = fcntl(new_server_socket, F_GETFL, 0); 
  fcntl(new_server_socket, F_SETFL, flags | O_NONBLOCK);
  mLog("Accept successfully!\n");
  return 0;
}
static int socket_recv(char* buffer,int length)
{
  int ret = 0;
//   fd_set read_flags;
//   struct timeval tv;
//   tv.tv_sec = 0;
//   tv.tv_usec = 10;
//   ret = select(new_server_socket, &read_flags, NULL, NULL, &tv);
//   if(ret == 0)//timeout
//     return 0;
//   else if(ret < 0)
//     return ret;
//   else
    ret = recv(new_server_socket,buffer,length,0);
  return ret;
}
static int socket_send(char* buffer,int length)
{
  if(new_server_socket < 0)
    return 0;
  if(send(new_server_socket,buffer,length,0)<0)
  {
    mLog("Server send Data Failed!\n");
    return -1;
  }
  return 0;
}
static int socket_close()
{
  close(new_server_socket);
  close(server_socket);
  return 0;
}
int packet_append(U_INT16 chan, char* buffer, int buff_length)
{
  BIT8 * pRd_Start;
  MIO_HDR_TYPE  *pRd_Packet = NULL; 

  pthread_mutex_lock(&Rd_Free_Q_Mut);
  GetPacket(pRd_Packet, Rd_Free_Q);
  pthread_mutex_unlock(&Rd_Free_Q_Mut);
  while(pRd_Packet == NULL) //the packet buffer is used by other
  {
    Task_yield();
    pthread_mutex_lock(&Rd_Free_Q_Mut);
    GetPacket(pRd_Packet, Rd_Free_Q);
    pthread_mutex_lock(&Rd_Free_Q_Mut);
  }
  mLog("get free_packet for Free_Q\n");
  pRd_Start = pRd_Packet->data_start + (BIT8 *)DMA_MEM;

  strncpy(pRd_Start,buffer,buff_length);
  pRd_Packet->data_length = buff_length;
  pRd_Packet->return_stat = RET_OK;
  pRd_Packet->comm_port   = chan;
  pthread_mutex_lock(&Rd_Input_Q_Mut);
  AppendPacket(pRd_Packet, Rd_Input_Q);
  pthread_mutex_unlock(&Rd_Input_Q_Mut);
  pRd_Packet = NULL;
  mLog("put rd_packet to Input_Q,Free_Q:%d,Input_Q:%d\n",Rd_Free_Q.num_entries,Rd_Input_Q.num_entries);

}

int packet_read(U_INT16 chan, char* buffer, int buff_length)
{
  U_INT16  enable_tx_int;
  U_INT16  Transmitting = FALSE;
  MIO_HDR_TYPE  *pWr_Packet = NULL;
  BIT8 * pWr_Data_Start;

  // mLog("recv_buffer:%s\n", pRd_Packet->data_start);
  enable_tx_int = FALSE;
  // if not sending packet and a new packet is avail: setup new packet 
  pthread_mutex_lock(&Wr_Output_Q_Mut);
  if((!Transmitting)&&(Wr_Output_Q[chan].num_entries > 0))
  {
    // get next packet 
    GetPacket(pWr_Packet,Wr_Output_Q[chan]);
    // determine 32 bit address 
    pWr_Data_Start =(BIT8 *)DMA_MEM + pWr_Packet->data_start;

    Transmitting = TRUE;
  }
  pthread_mutex_unlock(&Wr_Output_Q_Mut);
  if(Transmitting)
  {
    strncpy(buffer,pWr_Data_Start,pWr_Packet->data_length);
    buffer[pWr_Packet->data_length] = '\0';
    mLog("send buffer:%s\n",buffer);
    enable_tx_int = TRUE;
    pthread_mutex_lock(&Wr_Free_Q_Mut);
    AppendPacket(pWr_Packet, Wr_Free_Q);
    pthread_mutex_unlock(&Wr_Free_Q_Mut);
    Transmitting = FALSE;
    return strlen(buffer)+1;
  }
  return 0;
}
int SocketTask()
{ 
  char buffer[RD_BUF_SIZE];
  char buffer2[1];
  bzero(buffer, RD_BUF_SIZE);

  while(socket_init()<0 && allRun_flag)
  {
    mLog("the socket init is error\n");
    Task_yield();
  }
  while(allRun_flag)
  {
    if(socket_accept()<0)
    {
      mLog("the socket accept is error\n");
      Task_yield();
    }
    while (allRun_flag)
    {
      int buff_length = socket_recv(buffer,RD_BUF_SIZE);
      if(buff_length == 0)
      {
        mLog("recv error, client socket exits\n");
        close(new_server_socket);
        break;
      }
      else if(buff_length > 0)
      {
        strncpy(buffer+buff_length,"\0",1);
        mLog("recv buffer:%s\n",buffer);
        packet_append(DRTA_PORT,buffer, buff_length);

      }
      buff_length = packet_read(DRTA_PORT,buffer,RD_BUF_SIZE);
      if( buff_length> 0)
      {
        socket_send(buffer,buff_length);
      }
      Task_yield();
      /*
      char file_name[FILE_NAME_MAX_SIZE+1];
      bzero(file_name, FILE_NAME_MAX_SIZE+1);
      strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));
      mLog("%s\n",file_name);
      FILE * fp = fopen(file_name,"r");
      if(NULL == fp )
      {
      mLog("File:\t%s Not Found\n", file_name);
      }
      else
      {
      bzero(buffer, BUFFER_SIZE);
      int file_block_length = 0;
      //            while( (file_block_length = read(fp,buffer,BUFFER_SIZE))>0)
      while( (file_block_length = fread(buffer,sizeof(char),BUFFER_SIZE,fp))>0)
      {
      mLog("file_block_length = %d\n",file_block_length);
      if(send(new_server_socket,buffer,file_block_length,0)<0)
      {
      mLog("Send File:\t%s Failed\n", file_name);
      break;
      }
      bzero(buffer, BUFFER_SIZE);
      }
      //            close(fp);
      fclose(fp);
      mLog("File:\t%s Transfer Finished\n",file_name);
      }
      */
    }
  }
  socket_close();
  return 0;
}


